-
UI structure is expressed as code, e.g.
return <div>{thing}</div>.
Ripple
-
Origin:
-
2024/2025.
-
-
What it is:
-
A TypeScript-first, component-based UI framework. It combines ideas from React, Solid, and Svelte, with its own
.tsrxcomponent format/compiler.
-
-
UI syntax:
-
JSX-like markup.
-
-
Main idea:
-
Fine-grained reactivity + compiler-driven UI + TypeScript-native authoring. It tries to get the directness of Solid, the compiler approach of Svelte, and the familiar component model of React, while keeping the UI syntax close to JSX.
-
-
Has virtual DOM:
-
No.
-
-
Reactivity:
-
Fine-grained. The current API is
track().
-
Examples
-
Button increases a counter :
import { track } from "ripple";
const Counter = () => {
let &[count] = track(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => count++}>
Increment
</button>
</div>
);
};
Qwik
-
Origin:
-
2021, from the author of Inferno, who also worked on React and Svelte.
-
-
What it is:
-
Resumable UI framework
-
Focuses in SSR/startup performance.
-
Client JS is aggressively lazy-loadable.
-
The programming model is more framework-specific.
-
-
UI syntax:
-
JSX.
-
-
Main idea:
-
Don't hydrate; resume.
-
-
Has virtual DOM:
-
No.
-
-
Reactivity:
-
Fine-grained/resumable.
-
Examples
-
Button increases a counter :
import { component$, useSignal } from 'https://esm.sh/@builder.io/qwik';
import { render } from 'https://esm.sh/@builder.io/qwik';
export const Counter = component$(() => {
const count = useSignal(0);
return (
<div>
<p>Count: {count.value}</p>
<button onClick$={() => count.value++}>Increment</button>
</div>
);
});
render(document, <Counter />);
Solid
-
Origin:
-
2018-ish, 1.0 in 2021.
-
-
What it is:
-
Reactive UI framework.
-
-
UI syntax:
-
JSX.
-
-
Main idea:
-
Fine-grained reactivity.
-
Kinda like React, but with a Svelte-like compiler
-
"A more well thought-out and faster version of React".
-
-
Has virtual DOM:
-
No.
-
-
Reactivity:
-
Fine-grained signals
-
Examples
-
Button increases a counter :
import { createSignal } from "solid-js";
import { render } from "solid-js/web";
const Counter = () => {
const [count, setCount] = createSignal(0);
return (
<div>
<p>Count: {count()}</p>
<button onClick={() => setCount(count() + 1)}>
Increment
</button>
</div>
);
};
render(() => <Counter />, document.getElementById("app"));
-
Ex2 :
import { For, Show } from "solid-js";
export default function List(props) {
return (
<Show when={props.items.length} fallback={<div>No items</div>}>
<ul>
<For each={props.items}>{item => <li>{item.title}</li>}</For>
</ul>
</Show>
);
}
import { For } from "solid-js";
export default function Users(props) {
return <ul><For each={props.users}>{u => <li>{u.name}</li>}</For></ul>;
}
Inferno
-
.
Preact (Has VDOM)
-
Origin:
-
-
What it is:
-
Library, React-compatible.
-
-
UI syntax:
-
JSX.
-
-
Main idea:
-
React API with tiny footprint
-
-
Has virtual DOM:
-
Yes.
-
-
Reactivity:
-
Component re-execution.
-
Examples
-
Button increases a counter :
import { render } from "preact";
import { useState } from "preact/hooks";
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
};
render(<Counter />, document.getElementById("app"));
React (Has VDOM)
-
Origin:
-
Facebook, 2013.
-
-
What it is:
-
Library.
-
-
UI syntax:
-
JSX.
-
-
Main idea:
-
Component model + React ecosystem
-
-
Has virtual DOM:
-
Yes.
-
-
Reactivity:
-
Component re-execution
-
-
AJAX:
-
Via
fetch, Axios, or libraries like React Query; client-side rendering is driven by async data.
-
Asynchronous Behavior
-
React doesn’t fundamentally change how concurrency works—JS is still single-threaded—but it improves ergonomics and state management around asynchronous operations
-
React doesn’t add new concurrency primitives—it doesn’t give JS threads, parallelism, or async I/O that didn’t exist.
-
Everything React does is built on native JS: Promises, the event loop,
fetch, timers, etc. -
Automatic DOM diffing → no manual
innerHTMLmanipulation.-
Your component re-renders automatically when state changes.
-
In Vanilla JS :
fetch("/data") .then(res => res.text()) .then(html => document.getElementById("widget").innerHTML = html);-
You must track which element corresponds to which data.
-
Any additional async operations updating the same element require careful coordination.
-
-
In React :
const [data, setData] = useState(null); useEffect(() => { fetch("/data") .then(res => res.text()) .then(setData); }, []); return <div>{data || "Loading..."}</div>;-
React automatically re-renders the component when state changes.
-
No manual DOM manipulation.
-
Concurrency conflicts are minimized because state updates are batched and applied in order.
-
-
Examples
-
Button increases a counter :
import { useState } from "react";
import { createRoot } from "react-dom/client";
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
};
createRoot(document.getElementById("app")).render(<Counter />);
-
Simple async behavior :
function Component() {
const [data, setData] = React.useState(null);
React.useEffect(() => {
fetch("/data")
.then(res => res.json())
.then(setData);
}, []);
return <div>{data}</div>;
}
-
More complex async behavior :
function Dashboard() { const [widgets, setWidgets] = React.useState([]); const [loaded, setLoaded] = React.useState(false); React.useEffect(() => { Promise.all([ fetch("/data1").then(r => r.text()), fetch("/data2").then(r => r.text()), fetch("/data3").then(r => r.text()), ]) .then(results => setWidgets(results)) .finally(() => setLoaded(true)); }, []); return ( <div> {widgets.map((w, i) => ( <div key={i}>{w || "Loading..."}</div> ))} {loaded && <div>Dashboard loaded</div>} </div> ); }
Stencil
-
Origin:
-
-
What it is:
-
Web Components compiler
-
-
UI syntax:
-
JSX.
-
-
Main idea:
-
Compile JSX → Web Components
-
-
Has virtual DOM:
-
Compile-time/runtime machinery
-
-
Reactivity:
-
Component/state updates
-
Examples
-
Button increases a counter :
import { Component, State, h } from "@stencil/core";
@Component({
tag: "my-counter",
})
export class Counter {
@State() count = 0;
render = () => (
<div>
<p>Count: {this.count}</p>
<button onClick={() => this.count++}>
Increment
</button>
</div>
);
}
Mithril
-
Origin:
-
-
What it is:
-
Small UI framework
-
-
UI syntax:
-
m()/ JSX.
-
-
Main idea:
-
Small, self-contained MVC-ish UI
-
-
Has virtual DOM:
-
Yes.
-
-
Reactivity:
-
VDOM redraw
-
Examples
-
Button increases a counter :
import m from "mithril";
const Counter = {
count: 0,
view: () => (
m("div", [
m("p", `Count: ${Counter.count}`),
m(
"button",
{ onclick: () => Counter.count++ },
"Increment"
)
])
)
};
m.mount(document.getElementById("app"), Counter);